#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h> 
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <mysql/mysql.h>


#include "dir_commands.h"
#include "pathstack.h"
#include "sql_commands.h"
typedef struct{
    int type;
    int length;
    char value[4096];
}response_t;

int get_path(path_stack_t *s , char *buf,size_t size){
    if(s==NULL||buf == NULL){
            return -1;
    }
    if(s->top<0){
        if(size<2){
            return -1;//缓冲区太小
        }
        strcpy(buf,"/");
        return 0;
    }
    int offset = 0 ;
    for(int i = 0 ; i<=s->top;++i){
        int written = snprintf(buf + offset, size - offset, "/%s", s->dirs[i]);         // 要拼接的目录名
        if (written < 0 || written >= (size - offset)) {
            // 如果发生错误，或写入的字符等于或超过了剩余空间（意味着字符串被截断了）
            buf[0] = '\0'; // 清空缓冲区，表示无效结果
            return -1;     // 返回错误
        }
        // 更新偏移量
        offset += written;
    }
    return 0;
}

int build_real_path (path_stack_t *s,const char *user_root_path,char * real_path,size_t size){
    char virtual_path[4096]={0};
    if( get_path(s,virtual_path,sizeof(virtual_path))!=0){
        return -1;
    }
    int written;
    if(strcmp(virtual_path,"/")==0){
        written = snprintf(real_path,size,"%s",user_root_path);
    }else{
         written = snprintf(real_path,size,"%s%s",user_root_path,virtual_path);
    }
    if(written<0||written>=size){
        return -1;
    }
    return 0;
} 

int handle_pwd(int client_fd ,path_stack_t *s){
    char buf[4096]={0};
    if( get_path(s,buf,sizeof(buf))==0){
        strncat(buf, "\n", sizeof(buf) - strlen(buf) - 1);
        response_t response;
        response.type=103;
        response.length=strlen(buf);
        
        memcpy(response.value,buf,strlen(buf));
        send(client_fd,&response.type,sizeof(response.type),0);
        send(client_fd,&response.length,sizeof(response.length),0);
        send(client_fd,response.value,response.length,0);
        
        return 0;
    }
    else return -1;
}
int handle_ls(MYSQL *conn,path_stack_t *s,const char * user_root_path,char * result_buf,size_t size){
    char real_path[4096];
    bzero(result_buf,size);
    if ((get_path(s,real_path,sizeof(real_path))) != 0) {
        printf( "Error: Invalid path.\n");
        return -1;
    }
    char sql_query[5000]={0};
    snprintf(sql_query,sizeof(sql_query),"SELECT  user_filename, file_type FROM document WHERE parent_id = (SELECT document_id FROM document WHERE file_path = '%s') ",real_path);
    MYSQL_RES *result=NULL;
    db_execute(conn,sql_query,&result);
    MYSQL_ROW row;
    unsigned int num_fields = mysql_num_fields(result);

    // 3. 逐行遍历结果集
    while ((row = mysql_fetch_row(result))) {
        // 4. 在循环内部，逐列拼接
        for (unsigned int i = 0; i < num_fields; i++) {
            // row[i] 就是当前行、第 i 列的数据（是一个字符串）
            // 如果数据是 NULL，则显示 "NULL"
            const char* value = row[i] ? row[i] : "NULL";
            
            // 使用 strncat 安全地追加列数据和一個制表符作为分隔
            strncat(result_buf, value, size - strlen(result_buf) - 1);
            strncat(result_buf, "\t", size - strlen(result_buf) - 1);
        }
        // 每处理完一行，追加一个换行符
        strncat(result_buf, "\n", size - strlen(result_buf) - 1);
    }

    // 5. 释放结果集占用的内存，非常重要！
    mysql_free_result(result);


    return 0;

}


static int copy_stack(path_stack_t *dest, const path_stack_t *src) {//设置一个临时的栈试着操作cd
    init_stack(dest);

    for (int i = 0; i <= src->top; ++i) {
        if (push_dir(dest, src->dirs[i]) != 0) {
            free_stack(dest);
            return -1;
        }
    }
    return 0;
}
int handle_cd(MYSQL *conn,path_stack_t *s, const char* user_root_path, const char* target_dir) {
    // 0. 复制一份 target_dir，因为 strtok_r 会修改它
    char target_dir_copy[4096];
    strncpy(target_dir_copy, target_dir, sizeof(target_dir_copy) - 1);
    target_dir_copy[sizeof(target_dir_copy) - 1] = '\0';

    // 1. 创建一个临时栈来模拟 cd 操作
    path_stack_t temp_stack;
    if (copy_stack(&temp_stack, s) != 0) {
        return -1; // 内存错误
    }

    // 2. 如果是绝对路径 (以'/'开头)，先清空临时栈
    if (target_dir[0] == '/') {
        free_stack(&temp_stack);
        init_stack(&temp_stack);
    }

    // 3. 使用 strtok_r 循环处理路径的每一部分
    char *p_save = NULL;
    char *token = strtok_r(target_dir_copy, "/", &p_save);

    while (token != NULL) {
        if (strcmp(token, ".") == 0) {
            // 当前目录，什么也不做
        } else if (strcmp(token, "..") == 0) {
            // 上级目录，弹出一个元素
            char *popped = pop_dir(&temp_stack);
            if (popped) {
                free(popped);
            }
        } else if (strlen(token) > 0) { 
            // 普通目录名，压入栈
            if (push_dir(&temp_stack, token) != 0) {
                free_stack(&temp_stack);
                return -1; // 路径太深错误
            }
        }
        // 获取下一个 token
        token = strtok_r(NULL, "/", &p_save);
    }

    // 4. 所有情况最后都进行统一的路径验证
    char final_virtual_path[4096];
    if (get_path(&temp_stack, final_virtual_path, sizeof(final_virtual_path)) != 0) {
        free_stack(&temp_stack);
        return -1;
    }
    
    char sql_query[8192]={0};
    snprintf(sql_query, sizeof(sql_query), 
             "SELECT document_id FROM document WHERE file_path = '%s' AND file_type='d'",
             final_virtual_path);

    if(is_existed(conn, sql_query) != 0){
        fprintf(stderr,"cd failed: Directory '%s' not found or is not a directory.\n", final_virtual_path);
        free_stack(&temp_stack); // 验证失败，释放临时栈
        return -1;
    }
    
    // 5. 验证成功，用临时栈替换主栈
    free_stack(s);
    *s = temp_stack;

    return 0;   
}

